<template>
  <a-card>
    <h2>图书列表</h2>
    <a-divider/>
    <div class="search-wrapper">
      <div class="search">
        <a-input-search v-model:value="keyword"
                        enter-button
                        placeholder="根据书名检索"
                        @change="onSearch"></a-input-search>
      </div>
      <a-button @click="handleCreate">添加书籍</a-button>
    </div>
    <a-divider/>
    <a-table
      :columns="columns"
      :data-source="list"
      :pagination="false"
      :rowClassName="(record, index) => index % 2 === 1 ? 'table-striped' : null"
      :rowKey="record => record._id"
      bordered
      class="ant-table-striped"
      size="middle"
    >
      <template #publication_date="data">
        {{ formatMonth(data.record.publicationDate) }}
      </template>
      <template #actions="data">
        <a @click="$router.push(`/book/${data.text._id}`)">详情</a>
        <a-divider type="vertical"/>
        <a @click="handleUpdate(data.text)">更改</a>
        <a-divider type="vertical"/>
        <a-popconfirm title="确定要删除吗?" @confirm="handleDelete(data.text._id)">
          <a href="#">删除</a>
        </a-popconfirm>
      </template>
    </a-table>
    <a-pagination v-model:current="currentPage" v-model:pageSize="pageSizeRef"
                  :page-size-options="pageSizeOptions"
                  :total="total"
                  hideOnSinglePage
                  show-size-changer
                  style="margin-top: 20px;float: right;"
                  @change="handleTableChange" @showSizeChange="onShowSizeChange">
    </a-pagination>
    <a-modal :title="textMap[dialogStatus]" :visible="visible"
             @cancel="visible = false"
             @ok="dialogStatus === 'create' ? createData() : updateData()">
      <a-form :label-col="{span: 6}">
        <a-form-item label="书名">
          <a-input v-model:value="formData.name"/>
        </a-form-item>
        <a-form-item label="作者">
          <a-input v-model:value="formData.author"/>
        </a-form-item>
        <a-form-item label="ISBN">
          <a-input v-model:value="formData.ISBN"/>
        </a-form-item>
        <a-form-item label="出版社">
          <a-input v-model:value="formData.press"/>
        </a-form-item>
        <a-form-item label="出版日期">
          <a-month-picker v-model:value="formData.publicationDate"
                          format="YYYY-MM"
                          placeholder="选择日期"/>
        </a-form-item>
        <a-form-item label="类别">
          <a-select
            v-model:value="formData.type"
            style="width: 120px"
            @change="handleChange"
          >
            <a-select-option v-for="item in categories" :key="item._id" :value="item.title">{{ item.title }}</a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item label="价格">
          <a-input-number
            v-model:value="formData.price"
            :min="0" :precision="2"
            :step="10"
            :formatter="value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')"
            :parser="value => value.replace(/\$\s?|(,*)/g, '')"
          />
        </a-form-item>
      </a-form>
    </a-modal>
  </a-card>
</template>

<script>
import {
  Button,
  Card,
  DatePicker,
  Divider,
  Form,
  Input,
  InputNumber,
  message,
  Modal,
  Pagination,
  Popconfirm,
  Select,
  Table,
} from 'ant-design-vue'
import { onMounted, reactive, ref } from 'vue'
import { createBook, deleteBook, fetchBookList, updateBook } from '@/api/book'
import { deepClone, formatMonth } from '../../utils'
import moment from 'moment'
import { fetchCategoryList } from '@/api/classification'

const defaultFormData = {
  name: '',
  price: 0,
  author: '',
  press: '',
  ISBN: '',
  publicationDate: null,
  type: '',
}
export default {
  name: 'index',
  components: {
    ACard: Card,
    ADivider: Divider,
    AInputSearch: Input.Search,
    AButton: Button,
    ATable: Table,
    AModal: Modal,
    AForm: Form,
    AFormItem: Form.Item,
    AInput: Input,
    AMonthPicker: DatePicker.MonthPicker,
    AInputNumber: InputNumber,
    APagination: Pagination,
    APopconfirm: Popconfirm,
    ASelect: Select,
    ASelectOption: Select.Option
  },
  setup () {
    const columns = [
      {
        title: '书名',
        dataIndex: 'name',
      },
      {
        title: '分类',
        dataIndex: 'type',
      },
      {
        title: '作者',
        dataIndex: 'author',
      },
      {
        title: '出版时间',
        dataIndex: 'publicationDate',
        slots: {
          customRender: 'publication_date',
        },
      },
      {
        title: '价格',
        dataIndex: 'price',
      },
      {
        title: '操作',
        slots: {
          customRender: 'actions',
        },
      },
    ]
    let list = ref([])
    let total = ref(0)
    let currentPage = ref(1)
    let pageSizeRef = ref(5)
    const pageSizeOptions = ref(['5', '10', '15', '20'])
    const categories = ref([])
    let keyword = ref('')
    let dialogStatus = ref('')
    let textMap = reactive({
      update: '编辑书籍',
      create: '新增书籍',
    })

    const onSearch = () => {
      getList()
    }

    onMounted(async () => {
        await getClassification()
        await getList()
      },
    )
    const getList = async () => {
      await fetchBookList({
        page: currentPage.value,
        size: pageSizeRef.value,
        keyword: keyword.value,
      }).then(res => {
          list.value = res.data.list
          total.value = res.data.total
        },
      )
    }

    const getClassification = async () => {
      await fetchCategoryList().then(res => {
        categories.value = res.data
        },
      )
    }

    const visible = ref(false)
    const handleCreate = () => {
      Object.assign(formData, defaultFormData)
      dialogStatus.value = 'create'
      visible.value = true
    }

    const formData = reactive(deepClone(defaultFormData))
    const createData = async () => {
      const temp = deepClone(formData) // TODO 深拷贝一份表单
      temp.publicationDate = formData.publicationDate.valueOf() // 将 Moment对象 转化为 时间戳
      await createBook(temp).then(res => {
        message.success(res.msg)
        visible.value = false
      })
      await getList()
      Object.assign(formData, defaultFormData)
    }

    const handleTableChange = page => {
      currentPage.value = page
      getList()
    }
    const onShowSizeChange = (current, pageSize) => {
      pageSizeRef.value = pageSize
      getList()
    }

    const handleDelete = id => {
      const index = list.value.findIndex(element => element._id === id)
      deleteBook(id).then(res => message.success(res.msg))
      list.value.splice(index, 1)
    }

    const onDateChange = () => moment(formData.publicationDate)

    const handleUpdate = async record => {
      formData.id = record._id
      formData.author = record.author
      formData.name = record.name
      formData.price = record.price
      formData.type = record.type
      formData.ISBN = record.ISBN
      formData.press = record.press
      formData.publicationDate = moment(record.publicationDate)
      dialogStatus.value = 'update'
      visible.value = true
    }
    const updateData = async () => {
      const temp = deepClone(formData)
      temp.publicationDate = formData.publicationDate.valueOf()
      await updateBook(temp).then(res => {
        message.success(res.msg)
        visible.value = false
      })
      await getList()
      Object.assign(formData, defaultFormData)
    }
    const handleChange = value => {
      console.log(`selected ${value}`)
    }

    return {
      list,
      columns,
      visible,
      formData,
      keyword,
      dialogStatus,
      textMap,
      handleCreate,
      createData,
      handleUpdate,
      updateData,
      handleTableChange,
      onShowSizeChange,
      onSearch,
      onDateChange,
      handleDelete,
      pageSizeOptions,
      currentPage,
      pageSizeRef,
      total,
      formatMonth,

      categories,
      handleChange,
    }
  },
}
</script>

<style lang="scss" scoped>
.search-wrapper {
  display: flex;
  justify-content: space-between;

  .search {
    flex: 0.5;
  }
}

//noinspection CssInvalidPseudoSelector
.ant-table-striped :deep(.table-striped) {
  background-color: #fafafa;
}
</style>
